package service.calculator.bagnetified.sanmateo;

import java.math.BigDecimal;

import models.Payment;
import models.Rate;
import service.BillingCalculator;
import util.Rounder;

public class BagnetifiedSanMateoBillingCalculatorImpl implements BillingCalculator {

	public BigDecimal calculatePayment(Rate rate, Payment payment) {
        BigDecimal paymentCalculation = null;
        BagnetifiedSanMateoPaymentType paymentType = BagnetifiedSanMateoPaymentType
                .valueOf(payment.paymentType);
        final BigDecimal paymentHrs = BigDecimal.valueOf(payment.hours);
        final BigDecimal rateValue = rate.value;

        final BigDecimal ctpaRate = BigDecimal.valueOf(1.5625);
        final BigDecimal seaRate = BigDecimal.valueOf(1.625);

        switch (paymentType) {
        case BASIC:
        	BigDecimal basicBillingRate = calculateBasicBillingRate(rateValue);
            paymentCalculation = basicBillingRate.multiply(paymentHrs);
            break;
        case HP:
        case HPU:
        case LHRT:
        	paymentCalculation = rateValue.add(ctpaRate).add(seaRate).multiply(paymentHrs);
            break;
        case OT:
            BigDecimal otRate = rateValue.add(rateValue.multiply(BigDecimal.valueOf(0.25)));
            paymentCalculation = otRate.multiply(paymentHrs);
            break;
        case LHOT:
            BigDecimal lhotRate = rateValue.add(rateValue.multiply(BigDecimal.valueOf(1)));
            lhotRate = lhotRate.add(lhotRate.multiply(BigDecimal.valueOf(0.30)));
            paymentCalculation = lhotRate.multiply(paymentHrs);
            break;
        case SHRT:
        	BigDecimal shrtRate = rateValue.multiply(BigDecimal.valueOf(0.30));
            paymentCalculation = shrtRate.multiply(paymentHrs);
            break;
        case SUNDAY:
            BigDecimal sundayRate = rateValue.multiply(BigDecimal.valueOf(0.30));
            paymentCalculation = sundayRate.multiply(paymentHrs);
            break;
        case SHOT:
            BigDecimal shotRate = rateValue.add(rateValue.multiply(BigDecimal
                    .valueOf(0.30)));
            shotRate = shotRate.add(shotRate.multiply(BigDecimal.valueOf(0.30)));
            paymentCalculation = shotRate.multiply(paymentHrs);
            break;
        case RDRT:
            BigDecimal rdrtRate = rateValue.add(rateValue.multiply(BigDecimal.valueOf(0.3)));
            paymentCalculation = rdrtRate.multiply(paymentHrs);
            break;
        case RDOT:
            BigDecimal rdotRate = rateValue.add(rateValue.multiply(BigDecimal
                    .valueOf(0.30)));
            rdotRate = rdotRate.add(rdotRate.multiply(BigDecimal.valueOf(0.30)));
            paymentCalculation = rdotRate.multiply(paymentHrs);
            break;
        case RDLH:
            // Plus 160%
			BigDecimal rdlhRate = rateValue.add(rateValue.multiply(BigDecimal.valueOf(1.6)));
            paymentCalculation = rdlhRate.multiply(paymentHrs);
            break;
        case RDSH:
            // Plus 60%
			BigDecimal rdshRate = rateValue.add(rateValue.multiply(BigDecimal.valueOf(0.60)));
            paymentCalculation = rdshRate.multiply(paymentHrs);
            break;
        case NDRT:
            BigDecimal ndrtRate = rateValue.multiply(BigDecimal.valueOf(0.10));
            paymentCalculation = ndrtRate.multiply(paymentHrs);
            break;
        case NDLH:
        	// Only 20% of the rate
			BigDecimal ndlhRate = rateValue.multiply(BigDecimal.valueOf(0.2));
            paymentCalculation = ndlhRate.multiply(paymentHrs);
            break;
        case NDSH:
        	// Only 13% of the rate (10% of rate bec. of ND plus 3% bec. of SH)
			BigDecimal ndshRate = rateValue.multiply(BigDecimal.valueOf(0.13));
            paymentCalculation = ndshRate.multiply(paymentHrs);
            break;
        case CTPA:
        	paymentCalculation = ctpaRate.multiply(paymentHrs);
        	paymentCalculation = Rounder.roundup(paymentCalculation);
        	break;
        case SEA:
            paymentCalculation = seaRate.multiply(paymentHrs);
            break;
        default:
            System.out.println("WARNING: " + payment.paymentType
                    + " payment type not yet supported.");
        }

        if (paymentCalculation != null) {
        	paymentCalculation = Rounder.roundup(paymentCalculation);
        }

        return paymentCalculation;
    }

	private BigDecimal calculateBasicBillingRate(BigDecimal rateValue) {
		BigDecimal basicRate = BigDecimal.valueOf(0.00);
		BigDecimal governmentBenefits = computeGovernmentBenefitsPerHour();

		basicRate = basicRate.add(rateValue);
		basicRate = basicRate.add(governmentBenefits);

		return basicRate;
	}

	protected BigDecimal computeGovernmentBenefitsPerHour() {
		BigDecimal thirteenthMonthPayPerDay = BigDecimal.valueOf(24.25);
		BigDecimal sssPerDay = BigDecimal.valueOf(21.25);
		BigDecimal philhealthPerDay = BigDecimal.valueOf(3.85);
		BigDecimal pagIbigPerDay = BigDecimal.valueOf(3.85);
		BigDecimal ecMcPerDay = BigDecimal.valueOf(0.38);

		BigDecimal governmentBenefits = BigDecimal.valueOf(0.00);
		governmentBenefits = governmentBenefits.add(thirteenthMonthPayPerDay);
		governmentBenefits = governmentBenefits.add(sssPerDay);		
		governmentBenefits = governmentBenefits.add(philhealthPerDay);
		governmentBenefits = governmentBenefits.add(pagIbigPerDay);
		governmentBenefits = governmentBenefits.add(ecMcPerDay);

		governmentBenefits = governmentBenefits.divide(BigDecimal.valueOf(8)); // Compute per hour
		return governmentBenefits;
	}

}
